package com.jinlia.show.modules.base.system.service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jinlia.show.common.core.exception.MyRuntimeException;
import com.jinlia.show.modules.base.constant.SaleModelEnum;
import com.jinlia.show.modules.base.model.po.GoodsAttrPO;
import com.jinlia.show.modules.base.system.entity.*;
import com.jinlia.show.modules.base.system.mapper.GoodsMapper;
import com.jinlia.show.modules.base.model.form.GoodsForm;
import com.jinlia.show.modules.base.model.po.GoodsPO;
import com.jinlia.show.modules.base.model.query.GoodsQuery;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Data
@Service
public class GoodsMapperService extends ServiceImpl<GoodsMapper, Goods> {

    @Autowired
    GoodsLabelMapperService goodsTagMapperService;
    @Autowired
    GoodsLabelRelMapperService goodsTagRelMapperService;
    @Autowired
    GoodsAttrValueMapperService goodsAttrValueMapperService;
    @Autowired
    GoodsAttrMapperService goodsAttrMapperService;

    public Map<Long, GoodsPO> getMapGoodsVO(List<Long> goodsIds) {
        GoodsForm goodsForm = new GoodsForm();
        goodsForm.setGoodsIds(goodsIds);
        List<GoodsPO> voList = this.getBaseMapper().getVOList(goodsForm);
        return voList.stream().collect(Collectors.toMap(GoodsPO::getId, Function.identity()));
    }

    public Boolean saveOrUpPOList(List<GoodsPO> goodsPOs) {
        List<GoodsLabelRel> batchGoodsTagRel = new ArrayList<>();
        List<GoodsAttrValue> batchSkuItems = new ArrayList<>();
        /**
         * 对导入的商品进行分类
         */
        HashMap<String, List<GoodsPO>> mapGoodsPO = new HashMap<>();
        mapGoodsPO.put("idIsNull", goodsPOs.stream().filter(i -> i.getId() == null).collect(Collectors.toList()));
        mapGoodsPO.put("idNotNull", goodsPOs.stream().filter(i -> i.getId() != null).collect(Collectors.toList()));
        /**
         * 重新构造标签
         */
        if (!CollectionUtils.isEmpty(mapGoodsPO.get("idIsNull"))) {
            List<GoodsPO> add = mapGoodsPO.get("idIsNull");
            //校验重复的商品名
            Map<String, Goods> collect = this.lambdaQuery()
                    .in(Goods::getGoodsName, add.stream().map(GoodsPO::getGoodsName).collect(Collectors.toList()))
                    .list().stream()
                    .collect(Collectors.toMap(Goods::getGoodsName, Function.identity()));
            for (GoodsPO goodsPO : add) {
                if (collect.containsKey(goodsPO.getGoodsName())) {
                    goodsPO.setId(collect.get(goodsPO.getGoodsName()).getId());
                    mapGoodsPO.get("idNotNull").add(goodsPO);
                    continue;
                }
                this.save(GoodsPO.toEntity(goodsPO));
                /**
                 * 重新构造标签
                 */
                if (!CollectionUtils.isEmpty(goodsPO.getTags())) {
                    List<GoodsLabelRel> collectGoodsTagRel = goodsPO.getTags().stream().map(i -> {
                        GoodsLabelRel goodsTagRel = new GoodsLabelRel();
                        goodsTagRel.setGoodsId(goodsPO.getId());
                        goodsTagRel.setLabelId(i.getId());
                        return goodsTagRel;
                    }).collect(Collectors.toList());
                    batchGoodsTagRel.addAll(collectGoodsTagRel);
                }
                /**
                 * 重新构造属性
                 */
                if (!CollectionUtils.isEmpty(goodsPO.getGoodsAttrPOS())) {
                    goodsPO.getGoodsAttrPOS().forEach(i -> i.setGoodsId(goodsPO.getId()));//填充商品id
                    //
                    List<GoodsAttr> collectGoodsSku = goodsPO.getGoodsAttrPOS().stream().map(GoodsAttrPO::toEntity).collect(Collectors.toList());
                    goodsAttrMapperService.saveBatch(collectGoodsSku);
                    for (GoodsAttrPO goodsSku : goodsPO.getGoodsAttrPOS()) {
                        //填充goodsId和skuId
                        List<GoodsAttrValue> goodsSkuItems = goodsSku.getGoodsAttrValues();
                        goodsSkuItems.forEach(goodsSkuItem -> {
                            goodsSkuItem.setGoodsId(goodsPO.getId());
                            goodsSkuItem.setAttrId(goodsSku.getId());
                        });
                        batchSkuItems.addAll(goodsSkuItems);
                    }
                }

            }


        }
        if (!CollectionUtils.isEmpty(mapGoodsPO.get("idNotNull"))) {
            List<GoodsPO> idNotNull = mapGoodsPO.get("idNotNull");
            //校验更新后的名字与数据库中的名字是否重复
            Map<String, Goods> collect = this.lambdaQuery()
                    .in(Goods::getGoodsName, idNotNull.stream().map(GoodsPO::getGoodsName).collect(Collectors.toList()))
                    .list().stream()
                    .collect(Collectors.toMap(Goods::getGoodsName, Function.identity()));
            for (GoodsPO goodsPO : idNotNull) {
                if (collect.containsKey(goodsPO.getGoodsName()) && !goodsPO.getId().equals(collect.get(goodsPO.getGoodsName()).getId())) {
                    throw new MyRuntimeException(String.format("商品名(%S)重复,请确认后更新!!!", goodsPO.getGoodsName()));
                }
            }
            for (GoodsPO goodsPO : idNotNull) {
                this.updateById(GoodsPO.toEntity(goodsPO));
                if (!CollectionUtils.isEmpty(goodsPO.getTags())) {
                    //老标签
                    List<GoodsLabelRel> oldGoodsTagRel = goodsTagRelMapperService.lambdaQuery()
                            .eq(GoodsLabelRel::getGoodsId, goodsPO.getId())
                            .list();
                    //新标签
                    List<GoodsLabelRel> newGoodsTagRel = goodsPO.getTags().stream().map(i -> {
                        GoodsLabelRel goodsTagRel = new GoodsLabelRel();
                        goodsTagRel.setGoodsId(goodsPO.getId());
                        goodsTagRel.setLabelId(i.getId());
                        return goodsTagRel;
                    }).collect(Collectors.toList());
                    /**
                     * 比较集合差异1(需要新增的)
                     */
                    newGoodsTagRel.stream()
                            .filter(newTag -> oldGoodsTagRel.stream()
                                    .noneMatch(oldTag -> oldTag.getLabelId().equals(newTag.getLabelId())))
                            .forEach(newTag -> {
                                batchGoodsTagRel.add(newTag);
                            });
                    /**
                     * 比较集合差异2(需要删除的)
                     */
                    oldGoodsTagRel.stream().filter(oldTag -> newGoodsTagRel.stream()
                                    .noneMatch(newTag -> newTag.getLabelId().equals(oldTag.getLabelId())))
                            .forEach(oldTag -> {
                                //删除
                                goodsTagRelMapperService.removeById(oldTag.getId());
                            });
                }
                if (!CollectionUtils.isEmpty(goodsPO.getGoodsAttrPOS())) {
                    /**
                     * 删除原有属性
                     *
                     */
                    goodsAttrMapperService.lambdaUpdate()
                            .eq(GoodsAttr::getGoodsId, goodsPO.getId())
                            .remove();
                    goodsAttrValueMapperService.lambdaUpdate()
                            .eq(GoodsAttrValue::getGoodsId, goodsPO.getId())
                            .remove();
                    /**
                     * 新增新属性
                     */
                    goodsPO.getGoodsAttrPOS().forEach(i -> i.setGoodsId(goodsPO.getId()));//填充商品id
                    goodsAttrMapperService.saveBatch(goodsPO.getGoodsAttrPOS().stream().map(GoodsAttrPO::toEntity).collect(Collectors.toList()));
                    for (GoodsAttrPO goodsSku : goodsPO.getGoodsAttrPOS()) {
                        List<GoodsAttrValue> goodsSkuItems = goodsSku.getGoodsAttrValues();
                        goodsSkuItems.forEach(goodsSkuItem -> {
                            goodsSkuItem.setGoodsId(goodsPO.getId());
                            goodsSkuItem.setAttrId(goodsSku.getId());
                        });
                        batchSkuItems.addAll(goodsSkuItems);
                    }

                }
            }
        }
        if (!CollectionUtils.isEmpty(batchGoodsTagRel)) {
            goodsTagRelMapperService.saveBatch(batchGoodsTagRel);
        }
        if (!CollectionUtils.isEmpty(batchSkuItems)) {
            goodsAttrValueMapperService.saveBatch(batchSkuItems);
        }
        return Boolean.TRUE;
    }

    public IPage<GoodsPO> getPage(GoodsQuery goodsQuery) {
        // 构建分页参数
        Page<Goods> page = new Page<>(goodsQuery.getCurrent(), goodsQuery.getSize());
        //构造查询参数
        Page<GoodsPO> sysUserVOPage = this.getBaseMapper().getPagePO(page, goodsQuery);
        if (!CollectionUtils.isEmpty(sysUserVOPage.getRecords())) {
            Long[] goodsIds = sysUserVOPage.getRecords().stream().map(GoodsPO::getId).toArray(Long[]::new);
            Map<Long, List<GoodsAttrPO>> collect = goodsAttrMapperService.getPOsByGoodsId(goodsIds)
                    .stream()
                    .collect(Collectors.groupingBy(GoodsAttr::getGoodsId));

            for (GoodsPO record : sysUserVOPage.getRecords()) {
                //标签vo
                record.setTags(goodsTagMapperService.getGoodsTagsByGoodsId(record.getId()));
                if (collect.containsKey(record.getId())) {
                    record.setGoodsAttrPOS(collect.get(record.getId()));
                }
            }
        }
        return sysUserVOPage;
    }


    public void bindTags(Long goodsId, List<GoodsLabelRel> goodsTypeList) {
        goodsTagRelMapperService.remove(new LambdaQueryWrapper<GoodsLabelRel>().eq(GoodsLabelRel::getGoodsId, goodsId));
        if (!CollectionUtils.isEmpty(goodsTypeList)) {
            goodsTagRelMapperService.saveBatch(goodsTypeList);
        }
    }

    /**
     * 更新库存
     *
     * @param goodsId
     * @param changeNum
     */
    public void updateStockNum(Long goodsId, Integer changeNum) {
        Goods byId = this.getById(goodsId);
        if (SaleModelEnum.A.getValue().equals(byId.getSaleModel())) {
            //A:无库存禁止销售(商家接单时提醒)
            if (byId.getStockNum() <= 0 || byId.getStockNum() < Math.abs(changeNum)) {
                throw new MyRuntimeException("无库存禁止销售!!!");
            }
        } else if (SaleModelEnum.B.getValue().equals(byId.getSaleModel())) {
            //B:无库存提醒销售
            //todo 暂无处理
        } else if (SaleModelEnum.C.getValue().equals(byId.getSaleModel())) {
            //C:不限库存销售
            //todo 暂无处理
        }
        this.lambdaUpdate()
                .setSql("stock_num = stock_num + " + changeNum)
                .eq(Goods::getId, goodsId)
                .update();
    }

    /**
     * 更改销售模式
     */
    public void updateSaleModel(Goods goods) {
        if (Objects.isNull(goods.getId())) {
            throw new MyRuntimeException("更改销售模式缺少商品id!!!");
        }
        this.lambdaUpdate()
                .set(Objects.nonNull(goods.getStockNum()), Goods::getStockNum, goods.getStockNum()) //商品库存
                .set(Goods::getSaleModel, goods.getSaleModel())//销售模式 A:无库存禁止销售，B:无库存提醒销售,C不限库存销售
                .set(Objects.nonNull(goods.getGoodsName()), Goods::getGoodsName, goods.getGoodsName()) //商品库存
                .set(Objects.nonNull(goods.getPrice()), Goods::getPrice, goods.getPrice()) //商品库存
                .set(Objects.nonNull(goods.getWeight()), Goods::getWeight, goods.getWeight()) //商品库存
                .eq(Goods::getId, goods.getId())
                .update();
    }

    public JSONObject getDefaultGoodsAttrValue(Long id) {
        List<GoodsAttrPO> pOsByGoodsId = goodsAttrMapperService.getPOsByGoodsId(id);
        if (CollectionUtils.isEmpty(pOsByGoodsId)) {
            return new JSONObject();
        }
        JSONObject defaultGoodsAttrValueMap = new JSONObject();
        for (GoodsAttrPO goodsAttrPO : pOsByGoodsId) {
            defaultGoodsAttrValueMap.put(goodsAttrPO.getId().toString(), goodsAttrPO.getGoodsAttrValues().get(0).getId().toString());
        }
        return defaultGoodsAttrValueMap;
    }
}
